Java 套接字

起因

其实我不想写起因,一位面试人家让我写一个套接字,不会,输入输出,不会写。唉。。。 写代码吧,现在想想,我认真写java代码也没多久,慢慢来呗;

套接字

这个怎么理解呢,就是说tcp/udp在运输层,那么上层好多应用都要使用TCP,那么怎么区分呢?这时候就出现了套接字和端口,应用程序自己创建套接字,标记自己的端口,那么分包的时候就有了约束,传回的数据包,也可以根据端口找到位置;代码传送门

Demo时间

下面会有很多Demo 主要参考了 参考一参考二,主要参考;

Demo1

客户端获取服务器发过来的信息,然后就完了;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class TestClient {
public static void main(String args[]) {
try {
// 创建socket对象,指定服务器的ip地址,和服务器监听的端口号
// 客户端在new的时候,就发出了连接请求,服务器端就会进行处理,如果服务器端没有开启服务,那么
// 这时候就会找不到服务器,并同时抛出异常==》java.net.ConnectException: Connection
// refused: connect
Socket s1 = new Socket("127.0.0.1", 8888);
// 打开输入流
InputStream is = s1.getInputStream();
// 封装输入流
DataInputStream dis = new DataInputStream(is);
// 打印服务器端发送过来的信息
System.out.println(dis.readUTF());
System.out.println(dis.readUTF());
// 关闭输入流
dis.close();
// 关闭打开的socket对象
s1.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class TestServer {
public static void main(String args[]) {
try {
// 指定服务器端的端口号为8888
ServerSocket s = new ServerSocket(8888);
while (true) {
// 建立连接
Socket socket = s.accept();
// 打开输出流
OutputStream os = socket.getOutputStream();
// 封装输出流
DataOutputStream dos = new DataOutputStream(os);
// s<li>.getInetAddress()获取远程ip地址,s<li>.getPort()远程客户端的端口号
// 向客户端发送数据
dos.writeUTF("你好,客户端地址信息: " + socket.getInetAddress()
+ "\t客户端通信端口号: " + socket.getPort());
dos.writeUTF("i'm a server ,my name is colin!");
// 关闭打开的输出流
dos.close();
// 关闭打开的socket对象
socket.close();
}// 开始下一此循环
} catch (IOException e) {
e.printStackTrace();
}
}
}

题外话:

我们很容易服务器和客户端的形式基本类似这样:

1
2
3
4
5
6
7
8
ServerSocket s = new ServerSocket(8888);
while (true) {
Socket socket = s.accept();
/*stream的部分
*/
/*关闭流,关闭连接之类的
*/
}

socket如果接收不到,服务器就会就等着;
将其放在while(true)中,就一直监听;上一个关掉,监听下一个;

1
Socket socket = s.accept();

对于流来说,这里就很麻烦,一会儿就被绕晕了;输入,输出到底是针对谁来说的呢?
首先我们要清楚读和写;很简单吧,正因为简单,所以我就被弄糊涂了;
考虑我们在纸上写字;我们就将其简化为写;
然后我们抄写一遍,我们就需要先读出来,然后在写下;
这里我们会很容易想到我们写,我们读的;主题对象是我们;

但是考虑我们现在在敲代码;写是肯定的。但是真的在写吗?这是一个问题啊;我们通过键盘输入一段字符,字节流,给了机器,很明显的输入流对比,但是对系统来说,他是读的啊,他得知道你敲了啥啊;

所以输入流是这样一种对象: 读入你的输入,并且已相应的的格式,编码读给系统; 举个例子,大家来学校报道,报道通道相当于一个输入流,不断地来人,报道哪里会有人看你的档案,哦,你叫张三,然后学校知道你叫做张三;这就是输入流做的事情;

翻过来输出流,相当于什么呢?大家毕业了,排着队去照毕业照;不断地人流,到了照相馆照相;咔咔咔,大家就被输出了;这样不生动,我们换成劳动力市场,学校作为主体,输入流就是毕业时一个一个下发的档案,然后大家就可以去找工作了;学校就不管你了,你被输出了;

DEMO2

客户端一直说,服务器一直听;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class Client {
Socket client;
public Client() {
try {
client = new Socket("localhost", 7777);
OutputStream outputStream = client.getOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
InputStreamReader inputStreamReader = new InputStreamReader(System.in);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String a;
while (true) {
a = bufferedReader.readLine();
if (a.equals("bye"))
break;
dataOutputStream.writeUTF(a);
}
dataOutputStream.close();
bufferedReader.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new Client();
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class Server {
private Socket socket;
private ServerSocket ss;
public Server() throws IOException {
ss = new ServerSocket(7777);
socket = ss.accept();
InputStream inputStream = socket.getInputStream();
DataInputStream dataInputStream = new DataInputStream(inputStream);
while (true) {
String a = dataInputStream.readUTF();
if (a.equals("bye"))
break;
System.out.println(a);
br.readLine());
}
}
public static void main(String[] args) {
try {
new Server();
} catch (IOException e) {
e.printStackTrace();
}
}
}

在这里我们发现一个socket一边写,一边读,像不像是只是一个文件呢?

Demo3

客户端和服务器必须一人一句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public class TestClient {
public static void main(String[] args) {
try {
Socket socket = new Socket("localhost",8888);
OutputStream outputStream = socket.getOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
InputStream inputStream = socket.getInputStream();
DataInputStream dataInputStream = new DataInputStream(inputStream);
InputStreamReader inputStreamReader = new InputStreamReader(System.in);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String info;
String info1;
while (true)
{
info = bufferedReader.readLine();
dataOutputStream.writeUTF(info);
if (info == "bye")
break;
info1 = dataInputStream.readUTF();
System.out.println("服务器"+info1);
if (info1 == "bye")
break;
}
bufferedReader.close();
dataInputStream.close();
dataOutputStream.close();
socket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public class TestServer {
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket(8888);
Socket socket = serverSocket.accept();
OutputStream outputStream = socket.getOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
InputStream inputStream = socket.getInputStream();
DataInputStream dataInputStream = new DataInputStream(inputStream);
InputStreamReader inputStreamReader = new InputStreamReader(System.in);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String info;
String info1;
while (true)
{
info = dataInputStream.readUTF();
System.out.println("客户端说:"+ info);
if (info.equals("bye"))
break;
info1 = bufferedReader.readLine();
dataOutputStream.writeUTF(info1);
if (info1.equals("bye"))
break;
}
dataInputStream.close();
dataOutputStream.close();
bufferedReader.close();
socket.close();
serverSocket.close();
} catch (SocketException e)
{
System.out.println("网络异常");
}
catch (IOException e) {
e.printStackTrace();
}
}
}

其实这里我们就发现,这其实就是典型的一个TCP的连接了,一个一直监听,一个需要找到正确的ip和端口,才能正确获得socket;

Demo4

其实就是两个线程,一个读,一个写;像不像一个棉花,可以随时咬一口,或者随时放一块;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
public class TestClient {
public static void main(String[] args) {
try {
Socket socket = new Socket("localhost",8888);
InputStream inputStream = socket.getInputStream();
DataInputStream dataInputStream = new DataInputStream(inputStream);
OutputStream outputStream = socket.getOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
new MyClientReader(dataInputStream).start();
new MyClientWriter(dataOutputStream).start();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class MyClientReader extends Thread{
private DataInputStream dataInputStream;
public MyClientReader(DataInputStream dataInputStream) {
this.dataInputStream = dataInputStream;
}
@Override
public void run() {
String info;
try {
while (true)
{
info = dataInputStream.readUTF();
System.out.println("服务器说:"+info);
if (info.equals("bye")){
System.out.println("对方不想理你了");
System.exit(0);
}
}
} catch (IOException e) {
System.out.println("服务器死翘翘了");
e.printStackTrace();
}
}
}
class MyClientWriter extends Thread {
private DataOutputStream dataOutputStream;
public MyClientWriter(DataOutputStream dataOutputStream) {
this.dataOutputStream = dataOutputStream;
}
@Override
public void run() {
InputStreamReader inputStreamReader = new InputStreamReader(System.in);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String info;
try {
while (true)
{
info = bufferedReader.readLine();
dataOutputStream.writeUTF(info);
if (info.equals("bye"))
{
System.out.println("感谢使用");
System.exit(0);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
public class TestServer {
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket(8888);
Socket socket = serverSocket.accept();
OutputStream outputStream = socket.getOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
InputStream inputStream = socket.getInputStream();
DataInputStream dataInputStream = new DataInputStream(inputStream);
new MyClientReader(dataInputStream).start();
new MyServerWriter(dataOutputStream).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class MyServerReader extends Thread{
private DataInputStream dataInputStream;
public MyServerReader(DataInputStream dataInputStream) {
this.dataInputStream = dataInputStream;
}
@Override
public void run() {
String info;
try {
while (true)
{
info = dataInputStream.readUTF();
System.out.println("客户端说"+info);
if (info.equals("bye")){
System.out.println("对方不想理你了");
System.exit(0);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
class MyServerWriter extends Thread {
private DataOutputStream dataOutputStream;
public MyServerWriter(DataOutputStream dataOutputStream) {
this.dataOutputStream = dataOutputStream;
}
@Override
public void run() {
InputStreamReader inputStreamReader = new InputStreamReader(System.in);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String info;
try {
while (true)
{
info = bufferedReader.readLine();
dataOutputStream.writeUTF(info);
if (info.equals("bye"))
{
System.out.println("感谢使用");
System.exit(0);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

总结

  1. 其实一位套接字是很难的东西,学下来,感觉还是很容易理解的;
  2. 加油努力吧!